package com.wangzhixuan.commons.filestorage;

import com.wangzhixuan.commons.exception.BussinessException;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.HibernateValidator;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * 文件存储 业务接口类
 *
 * @author lixin
 */
public abstract class BaseFileStorageService<T extends FileStorageConfig> {

    protected T config;
    protected String fileName;
    protected String fileType;
    /**
     * 文件目录 默认为文件后缀
     */
    protected String directory;
    /**
     * 绝对路径 不包含文件名称
     */
    protected String savePath;
    /**
     * 访问路径 不包含文件名称
     */
    protected String baseUrl;

    /**
     * 设置云存储配置
     *
     * @param configMap 配置
     */
    public void setConfig(Map<String, String> configMap) {
        if (Objects.isNull(configMap)) {
            return;
        }
        config.mapToConfig(configMap);
    }

    public void setDirectory(String directory) {
        this.directory = directory;
    }

    /**
     * 检验配置是否正常
     *
     * @param config 配置
     */
    private void validConfig(FileStorageConfig config) {
        if (Objects.isNull(config)) {
            throw new BussinessException("请先设置云存储配置");
        }
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                .failFast(true)
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<FileStorageConfig>> valid = validator.validate(config);
        if (valid != null && !valid.isEmpty()) {
            config.setStatus(false);
        }
        if (!config.isStatus()) {
            throw new BussinessException(config.getType().name() + "云存储未开启或配置有误");
        }
    }

    /**
     * 上传
     *
     * @param file 文件流
     * @return 访问地址
     */
    public UploadResult uploadFile(MultipartFile file) {
        try {
            validConfig(config);
            fileName = file.getOriginalFilename();
            if (StringUtils.isNotBlank(fileName)) {
                buildPath();
                return UploadResult.builder().fileName(file.getOriginalFilename())
                        .newFileName(fileName).size(file.getSize())
                        .suffix(fileType).url(upload(file)).path(savePath)
                        .build();
            } else {
                throw new BussinessException("保存文件失败");
            }
        } catch (Exception e) {
            throw new BussinessException("保存文件失败", e);
        }
    }


    /**
     * 生成文件保存路径
     */
    private void buildPath() {
        fileType = fileName.lastIndexOf(".") > 0 ? fileName.substring(fileName.lastIndexOf(".") + 1) : "";
        String fullSuffix = StringUtils.isNotBlank(fileType) ? "." + fileType : "";
        //文件保存路径
        fileName = System.currentTimeMillis() + fullSuffix;
    }


    /**
     * 上传
     *
     * @param file 文件
     * @return 访问地址
     * @throws IOException
     */
    protected abstract String upload(MultipartFile file) throws IOException;
}
